using ICSharpCode.TextEditor.Document;
using System;
using System.Text;
namespace ICSharpCode.TextEditor.Actions
{
    public class Tab : AbstractEditAction
    {
        public static string GetIndentationString(IDocument document)
        {
            return Tab.GetIndentationString(document, null);
        }
        public static string GetIndentationString(IDocument document, TextArea textArea)
        {
            StringBuilder stringBuilder = new StringBuilder();
            if(document.TextEditorProperties.ConvertTabsToSpaces)
            {
                int indentationSize = document.TextEditorProperties.IndentationSize;
                if(textArea != null)
                {
                    int visualColumn = textArea.TextView.GetVisualColumn(textArea.Caret.Line, textArea.Caret.Column);
                    stringBuilder.Append(new string(' ', indentationSize - visualColumn % indentationSize));
                }
                else
                {
                    stringBuilder.Append(new string(' ', indentationSize));
                }
            }
            else
            {
                stringBuilder.Append('\t');
            }
            return stringBuilder.ToString();
        }
        private void InsertTabs(IDocument document, ISelection selection, int y1, int y2)
        {
            string indentationString = Tab.GetIndentationString(document);
            for(int i = y2 ; i >= y1 ; i--)
            {
                LineSegment lineSegment = document.GetLineSegment(i);
                if(i != y2 || i != selection.EndPosition.Y || selection.EndPosition.X != 0)
                {
                    document.Insert(lineSegment.Offset, indentationString);
                }
            }
        }
        private void InsertTabAtCaretPosition(TextArea textArea)
        {
            switch(textArea.Caret.CaretMode)
            {
                case CaretMode.InsertMode:
                    {
                        textArea.InsertString(Tab.GetIndentationString(textArea.Document, textArea));
                        break;
                    }
                case CaretMode.OverwriteMode:
                    {
                        string indentationString = Tab.GetIndentationString(textArea.Document, textArea);
                        textArea.ReplaceChar(indentationString[0]);
                        if(indentationString.Length > 1)
                        {
                            textArea.InsertString(indentationString.Substring(1));
                        }
                        break;
                    }
            }
            textArea.SetDesiredColumn();
        }
        public override void Execute(TextArea textArea)
        {
            if(textArea.SelectionManager.SelectionIsReadonly)
            {
                return;
            }
            int indentationSize = textArea.Document.TextEditorProperties.IndentationSize;
            textArea.Document.UndoStack.StartUndoGroup();
            if(textArea.SelectionManager.HasSomethingSelected)
            {
                var sCollection = new System.Collections.Generic.List<ISelection>(textArea.SelectionManager.SelectionCollection);
                textArea.BeginUpdate();
                foreach(ISelection current in sCollection)
                {
                    TextLocation start = current.StartPosition
                                , end = current.EndPosition;
                    int y = start.Y;
                    int y2 = end.Y;
                    if(y == y2)
                    {
                        this.InsertTabAtCaretPosition(textArea);
                        break;
                    }
                    this.InsertTabs(textArea.Document, current, y, y2);
                    textArea.Document.RequestUpdate(new TextAreaUpdate(TextAreaUpdateType.LinesBetween, y, y2));

                    start.Column = Math.Max(0, start.Column + indentationSize);
                    end.Column = Math.Max(0, end.Column + indentationSize);

                    textArea.SelectionManager.SetSelection(start, end);

                }

                textArea.Caret.Position = new TextLocation(Math.Max(0, textArea.Caret.Column + indentationSize), textArea.Caret.Line);
                textArea.EndUpdate();

                textArea.Document.CommitUpdate();
                textArea.AutoClearSelection = false;
            }
            else
            {
                this.InsertTabAtCaretPosition(textArea);
            }
            textArea.Document.UndoStack.EndUndoGroup();
        }
    }
}
